package cn.lysj.framework.common.validate.validate;

import cn.lysj.framework.common.validate.constant.Message;
import cn.lysj.framework.common.validate.entity.Entity;
import cn.lysj.framework.common.validate.entity.Medusa;
import cn.lysj.framework.common.validate.exception.ValidatorException;
import cn.lysj.framework.common.validate.helper.AnnotationHelper;
import cn.lysj.framework.common.validate.param.Param;
import java.lang.annotation.Annotation;

/**
 * @author ww
 * @date 2018-08-22 10:43
 * @Description 校验的抽象类，所有的校验类都需要继承该抽象类，编写init方法和validate逻辑
 */
public abstract class AbstractValidate<T> {
    //注解
    public T annotation;
    //错误提示
    private String msg;
    //组别
    private Class<?>[] groups = null;

    /**
     * explain: 校验逻辑方法
     * @param entity 待校验的对象
     **/
    public abstract boolean validate(Entity entity);

    /**
     * explain: 初始化方法，所有的校验子类在继承该抽象类后需要编写init方法设置错误提示消息或者其他自定义操作
     **/
    public abstract void init();

    /**
     * explain: 设置校验的组别
     * @param groups 分组
     **/
    public void setGroups(Class<?>[] groups) {
        this.groups = groups;
    }

    /**
     * explain: 设置默认校验不通过提示信息
     * @param annotation 校验注解
     * @throws  ValidatorException 当注解没有 message方法时，抛出异常
     * @org.yxs.medusa.annotation.Email(clazz=class org.yxs.medusa.validate.EmailValidate, value=必须为邮箱)
     **/
    private void enabledDefaultMsg(Annotation annotation) {
        Class<? extends Annotation> clazz = AnnotationHelper.choice(annotation);
        try {
            setMsg(String.valueOf(clazz.getMethod(Param.MESSAGE).getDefaultValue()));
        } catch (NoSuchMethodException e) {
            throw new ValidatorException(e);
        }
    }

    /**
     * explain: 设置校验不通过提示信息
     * @param msg 提示内容
     **/
    public void setMsg(String msg) {
        this.msg = msg;
    }

    /**
     * explain: 获取校验返回值 {@link Medusa}
     * @param entity {@link Entity} 该参数包含属性的注解，属性Field对象，以及属性的值
     * date 2016/5/25 - 11:50
     **/
    public Medusa result(Entity entity) {
        //设置annotation对象为属性的校验注解
        //@cn.lysj.framework.util.validate.annotation.ForeignKey(...)
        annotation = (T) entity.getAnnotation();
        //执行初始化方法
        init();
        //执行校验逻辑  在子类里面判断
        boolean flag = validate(entity);
        //返回校验结果
        return new Medusa(flag, entity.getField(), flag ? Message.ALLOW : this.msg, entity.isSort(), this.groups);
    }
}
